﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using OpenMcdf;
using System.Text.RegularExpressions;

namespace OracleOleRecovery
{
    public class PdfRecovery
    {
        public static Byte[] RecoverPdf(Byte[] compoundFile){

            PdfRecoveryStatus status = RecoverPdfWithStatus(compoundFile);
            return status.pdfFile;
            
        }

        public static PdfRecoveryStatus RecoverPdfWithStatus(Byte[] compoundFile)
        {
            Regex pdfVersion = new Regex("PDF-([0-9\\.]+)");
            PdfRecoveryStatus status = new PdfRecoveryStatus();
            Byte[] decodedPdf = null;

            Stream stream = new MemoryStream(compoundFile);
            CompoundFile cf = new CompoundFile(stream);

            VisitedEntryAction va = delegate(CFItem item)
            {

                /// PDF file has to be bigger than 500 bytes right? Not sure 
                /// how to optimally size this
                if (item.IsStream && item.Size > 500)
                {

                    CFStream theStream = (CFStream)item;
                    Byte[] encodedPdf = theStream.GetData();

                    /// convert to a string so we can search for SOF/EOF
                    System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
                    string pdfText = enc.GetString(encodedPdf);

                    int startOfFilePosition = pdfText.IndexOf("%PDF");
                    int endOfFilePosition = pdfText.LastIndexOf("%%EOF");

                    if (startOfFilePosition > -1 && endOfFilePosition > startOfFilePosition)
                    {

                        int arrayLength = endOfFilePosition - startOfFilePosition + 5;
                        decodedPdf = new Byte[arrayLength];
                        Array.Copy(encodedPdf, startOfFilePosition, decodedPdf, 0, arrayLength);
                        status.foundIn = theStream.Name;
                        status.pdfFile = decodedPdf;
                        MatchCollection mc = pdfVersion.Matches(pdfText, (int)startOfFilePosition);
                        if (mc.Count > 0 && mc[0].Groups.Count > 1)
                        {
                            status.pdfVersion = mc[0].Groups[1].Value;
                        }
                        return;
                    }
                }
            };

            cf.RootStorage.VisitEntries(va, true);
            return status;
        }

    }
}
